﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.DocumentSet;

namespace SharePointOnlineServices
{
    public class DocumentSetUtility
    {
        private ClientContext context;

        public DocumentSetUtility(ClientContext context)
        {
            this.context = context;
        }

        public void SaveDocumentSet(DocumentSetSaveProperties saveProperties)
        {
            var list = this.RetriveList(context, saveProperties.ListName);
            var listItems = this.LookupItemByTitle(context, list, saveProperties.DocumentSetItemTitle);

            // If the Document Set doesn't exist, create it
            if (!listItems.Any())
            {
                this.CreateDocumentSet(context, list, saveProperties.DocumentSetContentTypeName, saveProperties.DocumentSetItemTitle);

                listItems = this.LookupItemByTitle(context, list, saveProperties.DocumentSetItemTitle);
            }

            // Set any field values into the document set
            foreach (var listItem in listItems)
            {
                context.Load(listItem);

                foreach (var keyValuePair in saveProperties.FieldNameValueCollection)
                {
                    if (listItem.FieldValues.ContainsKey(keyValuePair.Key))
                    {
                        listItem.FieldValues[keyValuePair.Key] = keyValuePair.Value;
                        listItem[keyValuePair.Key] = keyValuePair.Value;
                    }
                }

                listItem.Update();
            }

            list.Update();
            context.ExecuteQuery();
        }

        private List RetriveList(ClientContext context, string listName)
        {
            var list = context.Web.Lists.GetByTitle(listName);
            context.Load(list);
            context.ExecuteQuery();

            if (list == null || list.Id == Guid.Empty)
                throw new Exception(string.Format("The specified list {0} does not exist.", listName));

            return list;
        }

        private ListItemCollection LookupItemByTitle(ClientContext context, List list, string title)
        {
            CamlQuery camlQuery = new CamlQuery();
            camlQuery.ViewXml = string.Format(@"<View>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name='Title'/>
                <Value Type='Text'>{0}</Value>
            </Eq>
        </Where>
    </Query>
</View>", title);

            ListItemCollection listItems = list.GetItems(camlQuery);
            context.Load(listItems);
            context.ExecuteQuery();

            return listItems;
        }

        private void CreateDocumentSet(ClientContext context, List list, string contentTypeName, string documentSetTitle)
        {
            // Look up the content type for the Document Set
            context.Load(list.ContentTypes, cts => cts.Where(ct => ct.Name == contentTypeName));
            context.ExecuteQuery();

            if (!list.ContentTypes.Any())
                throw new Exception(string.Format("Document Set creation failed - Cannot find associated content type {0}.", contentTypeName));

            var documentSetContentType = list.ContentTypes.First();

            // Create the Doc Set
            var ds = DocumentSet.Create(context, list.RootFolder, documentSetTitle, documentSetContentType.Id);
            context.ExecuteQuery();
        }
    }
}
